Skip to content

feat(ads-client): roundtrip cap key for spoc impression callbacks (AC-125)#7442

Open
jonesetc wants to merge 2 commits into
mozilla:mainfrom
jonesetc:ads-client-roundtrip-cap-key
Open

feat(ads-client): roundtrip cap key for spoc impression callbacks (AC-125)#7442
jonesetc wants to merge 2 commits into
mozilla:mainfrom
jonesetc:ads-client-roundtrip-cap-key

Conversation

@jonesetc

Copy link
Copy Markdown
Member

Add roundtripping of cap_key in sposored content impression callback urls. This value is currently just discarded, but in the future will be used to keep a rolling count of impressions in the last 24 hours on device to make sure sponsored content is not being shown too often.

This does not change any internal or external APIs, and does not require an entry in the changelog

Pull Request checklist

  • Breaking changes: This PR follows our breaking change policy
    • This PR follows the breaking change policy:
      • This PR has no breaking API changes, or
      • There are corresponding PRs for our consumer applications that resolve the breaking changes and have been approved
  • Quality: This PR builds and tests run cleanly
    • Note:
      • For changes that need extra cross-platform testing, consider adding [ci full] to the PR title.
      • If this pull request includes a breaking change, consider cutting a new release after merging.
  • Tests: This PR includes thorough tests or an explanation of why it does not
  • Changelog: This PR includes a changelog entry in CHANGELOG.md or an explanation of why it does not need one
    • Any breaking changes to Swift or Kotlin binding APIs are noted explicitly
  • Dependencies: This PR follows our dependency management guidelines
    • Any new dependencies are accompanied by a summary of the due diligence applied in selecting them.

@jonesetc jonesetc requested a review from Almaju June 22, 2026 18:35
@jonesetc jonesetc requested a review from a team as a code owner June 22, 2026 18:35
@jonesetc jonesetc force-pushed the ads-client-roundtrip-cap-key branch 2 times, most recently from 5ce339a to bc47c9b Compare June 22, 2026 19:52

fn impression_enriching_params(&self) -> Vec<(String, String)> {
vec![("cap_key".to_owned(), self.caps.cap_key.clone())]
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can do fn impression_enriching_params(&self) -> [(&str, &str); 1] to have zero allocation (no Vec, no String)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem with the &str (or any reference returned) in there is that this result is used during the mutable borrow of callbacks_mut, so those would have to be cloned anyway. I think returning something like Option<IntoIterator<(String, String)>> should be possible and avoid allocation in the non-spoc case and just a single small array in the spoc case.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just went ahead and simplified it instead of worrying about iterators or refs. Now there is just a method that returns an optional cap_key, by default None, and spoc returns a string. The string would need to be owned eventually like i mentioned because of the mutable borrow for callbacks. so I figured just returning the string made more sense than making the caller do something like:

let cap_key = ad.cap_key().map(String::from)

Comment thread components/ads-client/src/client.rs Outdated
.query_pairs_mut()
.append_pair("request_hash", &hash_str);
.append_pair("request_hash", &hash_str)
.extend_pairs(impression_enriching_params);

@Almaju Almaju Jun 23, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we already have the request_hash acting as a unique identifier up top, could storing it in the SQLite table "impression_log" be a cleaner alternative here?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A request hash maps to an an ad response, each of which contains 0-* spocs. Each spoc has its own cap key. So going just from the request hash to a single cap key doesn't work.

A much messier thing that could be done would be to just map the impression url itself to the block key, but that is assuming that the mapping between spoc:impression url:cap key is always 1:1:1. Actually getting back to the cap key directly makes the fewest assumptions and allows the cap keys to do more complex things from the server like "all of these spocs have cap key A, and these have cap key B" to have group limits instead of just per individual spoc.

@jonesetc jonesetc force-pushed the ads-client-roundtrip-cap-key branch from bc47c9b to e50e0d5 Compare June 24, 2026 00:07
@jonesetc jonesetc requested a review from Almaju June 24, 2026 00:18

@Almaju Almaju left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the changes, lgtm!
We might be able refactor this later with async model because we will need some AdStore that can hold stateful data such as request hash or cap key but this looks great for now and the current sync stateless model we have!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants